package main

import (
	"fmt"
	"github.com/alexflint/go-arg"
	"github.com/grid-x/modbus"
	"time"
)

var client modbus.Client
var handler modbus.ClientHandler

type Args struct {
	Id        int    `default:"1" help:"Modbus从机地址，默认：1"`
	Connector string `default:"COM1" help:"连接地址，串口连接示例：COM1、/dev/ttyS0 、 /usr/dev/serial/COM1，IP连接示例：192.168.100.108:10001"`
	Mode      string `default:"RTU" help:"连接模式，默认：RTU（可选：RTU、ASCII、TCP、RTUoverTCP、ASCIIoverTCP，其中RTU和ASCII是串口连接，其它都是IP连接）"`
	RS485     bool   `default:"false"`
	Addr      int    `default:"0" help:"Modbus寄存器地址（10进制格式）：默认：0"`
	Quantity  int    `default:"10" help:"Modbus读取的寄存器数量：默认：10"`
	Func      string `default:"03" help:"Modbus功能码：默认：03（可选：01、02、03、04）"`
	BaudRate  int    `default:"9600" help:"串口波特率：默认：9600（可选：1200、2400、4800、9600、19200、38400、115200）"`
	DataBits  int    `default:"8" help:"串口数据位：默认：8（可选：5、6、7、8）"`
	StopBits  int    `default:"1" help:"串口停止位：默认：1（可选：1、2）"`
	Parity    string `default:"N" help:"串口奇偶校验：默认：N（可选：N（无校验）、 E（偶校验）、O（奇校验））"`
}

func main() {
	args := Args{}
	arg.MustParse(&args)
	fmt.Println(args)

	switch args.Mode {
	case "RTU":
		h := modbus.NewRTUClientHandler(args.Connector)
		h.BaudRate = args.BaudRate
		h.DataBits = args.DataBits
		h.Parity = args.Parity
		h.StopBits = args.StopBits
		h.SlaveID = byte(args.Id)
		h.Timeout = 5 * time.Second
		h.RS485.Enabled = args.RS485
		handler = h
	case "ASCII":
		h := modbus.NewASCIIClientHandler(args.Connector)
		h.BaudRate = args.BaudRate
		h.DataBits = args.DataBits
		h.Parity = args.Parity
		h.StopBits = args.StopBits
		h.SlaveID = byte(args.Id)
		h.Timeout = 5 * time.Second
		h.RS485.Enabled = args.RS485
		handler = h
	case "TCP":
		h := modbus.NewTCPClientHandler(args.Connector)
		h.SlaveID = byte(args.Id)
		h.Timeout = 5 * time.Second
		handler = h
	case "RTUoverTCP":
		h := modbus.NewRTUOverTCPClientHandler(args.Connector)
		h.SlaveID = byte(args.Id)
		h.Timeout = 5 * time.Second
		handler = h
	case "ASCIIoverTCP":
		h := modbus.NewASCIIOverTCPClientHandler(args.Connector)
		h.SlaveID = byte(args.Id)
		h.Timeout = 5 * time.Second
		handler = h
	default:
		panic("不支持的模式：" + args.Mode)
		return
	}

	err := handler.Connect()
	if err != nil {
		panic("connect: " + err.Error())
	}
	defer handler.Close()

	client := modbus.NewClient(handler)
	var results []byte
	switch args.Func {
	case "01":
		results, err = client.ReadCoils(uint16(args.Addr), uint16(args.Quantity))
	case "02":
		results, err = client.ReadDiscreteInputs(uint16(args.Addr), uint16(args.Quantity))
	case "03":
		results, err = client.ReadHoldingRegisters(uint16(args.Addr), uint16(args.Quantity))
	case "04":
		results, err = client.ReadInputRegisters(uint16(args.Addr), uint16(args.Quantity))
	default:
		panic("不支持的功能码：" + args.Func)
	}
	//results, err := client.ReadHoldingRegisters(400, uint16(args.Quantity))
	if err != nil {
		if len(results) > 0 {
			fmt.Printf("results err src: %v\n", results)
			fmt.Printf("results err hex: ")
			for i := 0; i < len(results); i++ {
				fmt.Printf("%02X ", results[i])
			}
		}
		panic(err)
	}
	fmt.Printf("results src: %v\n", results)
	fmt.Printf("results hex: ")
	for i := 0; i < len(results); i++ {
		fmt.Printf("%02X ", results[i])
	}
}
